package MapperModule

import (
	"fmt"
	"frame/logger/HLogger"
	"database/sql"
	"reflect"
	"strings"
	"strconv"
	"unsafe"
)

var logger = HLogger.GetHLogger("MapperModule")

type MapperModule struct {
	MapperName string
	GdbcName   string
	BeginTx    bool
	TX         *sql.Tx
	TXID       int64
}

func CreateMapperModule(tx *sql.Tx,mapperStruct interface{}) (MapperModule) {
	var mappermodule MapperModule
	var mapperStructName =reflect.ValueOf(mapperStruct).FieldByName("Name").String()
	var mapperStructGdbcname =reflect.ValueOf(mapperStruct).FieldByName("Gdbcname").String()
	if(tx==nil){
		mappermodule = MapperModule{MapperName: mapperStructName, GdbcName:mapperStructGdbcname, BeginTx: false}
	}else{
		var txnId,_ = strconv.ParseInt(fmt.Sprintf("%p", unsafe.Pointer(tx))[2:],16,0)
		mappermodule = MapperModule{MapperName:mapperStructName, GdbcName: mapperStructGdbcname, BeginTx: true,TX:tx,TXID:int64(txnId)}
	}
	return mappermodule
}

type DbAnTxInterface interface {
	Prepare(query string) (*sql.Stmt, error)
}

func INSERTONE_TEMPLATE(mappermodule MapperModule, istruct interface{}) (int) {
	result, err := EXEC_TEMPLATE(mappermodule, "insertone", istruct)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return 0
	}
	return result
}
func SELECTBYPK_TEMPLATE(mappermodule MapperModule, istruct interface{}, returntype *reflect.Type) (interface{}) {
	result, err := QUERY_TEMPLATE(mappermodule, "selectbypk", istruct)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return nil
	}
	if (len(result) == 1) {//拼装返回结构体
		resultMap := result[0]
		returnStruct := reflect.New(*returntype).Elem() //创建返回结果结构体
		for i := 0; i < (*returntype).NumField(); i++ {
			fieldType := (*returntype).Field(i).Type //获取字段类型,即reflect.TypeOf(XXXX).Field(i).Type		，类型为Type
			fieldValue := returnStruct.Field(i)      //获取字段，即reflect.New(*returntype).Elem().Field(i)	，类型为Value
			//从数据库查询结果中寻找不区分大小写的key
			var fieldName = (*returntype).Field(i).Name;
			var fieldRealValue interface{}
			for k,v := range resultMap{
				if(strings.ToUpper(k)==strings.ToUpper(fieldName)){
					fieldRealValue = v
					break
				}
			}
			//根据类型设置写入方式
			switch fieldType.Kind() {
			case reflect.Int, reflect.Int8, reflect.Int16,
				reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8,
				reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Ptr:
				fieldValue.SetInt(fieldRealValue.(int64))
			case reflect.Float32, reflect.Float64:
				fieldValue.SetFloat(fieldRealValue.(float64))
			case reflect.String, reflect.Slice:
				fieldValue.SetString(fieldRealValue.(string))
			default:
				logger.Error("其他类型的字段暂不支持fieldType()[" + fieldType.Kind().String() + "]")
			}
		}
		return returnStruct.Interface()//转换为struct返回
	} else {
		logger.Error("数据库操作异常,SELECTBYPK查出["+strconv.Itoa(len(result))+"]条记录")
		return nil
	}
}
func UPDATEBYPK_TEMPLATE(mappermodule MapperModule, istruct interface{}) (int) {
	result, err := EXEC_TEMPLATE(mappermodule, "updatebypk", istruct)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return 0
	}
	return result
}
func DELETEBYPK_TEMPLATE(mappermodule MapperModule, istruct interface{}) (int) {
	result, err := EXEC_TEMPLATE(mappermodule, "deletebypk", istruct)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return 0
	}
	return result
}
func SELECTONE_TEMPLATE(mappermodule MapperModule, istruct interface{}, returntype *reflect.Type) (interface{}) {
	result, err := QUERY_TEMPLATE(mappermodule, "selectone", istruct)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return nil
	}
	if (len(result) == 1) {//拼装返回结构体
		resultMap := result[0]
		returnStruct := reflect.New(*returntype).Elem() //创建返回结果结构体
		for i := 0; i < (*returntype).NumField(); i++ {
			fieldType := (*returntype).Field(i).Type //获取字段类型,即reflect.TypeOf(XXXX).Field(i).Type		，类型为Type
			fieldValue := returnStruct.Field(i)      //获取字段，即reflect.New(*returntype).Elem().Field(i)	，类型为Value
			//从数据库查询结果中寻找不区分大小写的key
			var fieldName = (*returntype).Field(i).Name;
			var fieldRealValue interface{}
			for k,v := range resultMap{
				if(strings.ToUpper(k)==strings.ToUpper(fieldName)){
					fieldRealValue = v
					break
				}
			}
			//根据类型设置写入方式
			switch fieldType.Kind() {
			case reflect.Int, reflect.Int8, reflect.Int16,
				reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8,
				reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Ptr:
				fieldValue.SetInt(fieldRealValue.(int64))
			case reflect.Float32, reflect.Float64:
				fieldValue.SetFloat(fieldRealValue.(float64))
			case reflect.String, reflect.Slice:
				fieldValue.SetString(fieldRealValue.(string))
			default:
				logger.Error("其他类型的字段暂不支持fieldType()[" + fieldType.Kind().String() + "]")
			}
		}
		return returnStruct.Interface()//转换为struct返回
	} else {
		logger.Error("数据库操作异常,SELECTBYPK查出多条记录")
		return nil
	}
}
func SELECTLIST_TEMPLATE(mappermodule MapperModule, istruct interface{}, returntype *reflect.Type) ([]interface{}) {
	result, err := QUERY_TEMPLATE(mappermodule, "selectlist", istruct)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return nil
	}
	var returnslice = make([]interface{},0,1)
	for _,cell := range result {
		returnStruct := reflect.New(*returntype).Elem() //创建返回结果结构体
		for i := 0; i < (*returntype).NumField(); i++ {
			fieldType := (*returntype).Field(i).Type //获取字段类型,即reflect.TypeOf(XXXX).Field(i).Type		，类型为Type
			fieldValue := returnStruct.Field(i)      //获取字段，即reflect.New(*returntype).Elem().Field(i)	，类型为Value
			//从数据库查询结果中寻找不区分大小写的key
			var fieldName = (*returntype).Field(i).Name;
			var fieldRealValue interface{}
			for k,v := range cell{
				if(strings.ToUpper(k)==strings.ToUpper(fieldName)){
					fieldRealValue = v
					break
				}
			}
			//根据类型设置写入方式
			switch fieldType.Kind() {
			case reflect.Int, reflect.Int8, reflect.Int16,
				reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8,
				reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Ptr:
				fieldValue.SetInt(fieldRealValue.(int64))
			case reflect.Float32, reflect.Float64:
				fieldValue.SetFloat(fieldRealValue.(float64))
			case reflect.String, reflect.Slice:
				fieldValue.SetString(fieldRealValue.(string))
			default:
				logger.Error("其他类型的字段暂不支持fieldType()[" + fieldType.Kind().String() + "]")
			}
		}
		returnslice = append(returnslice,returnStruct)
	}
	return returnslice
}

func QUERYONEMAP_TEMPLATE(mappermodule MapperModule, parammap map[string]interface{}) (map[string]interface{}) {
	result, err := QUERY_TEMPLATE(mappermodule, "queryonemap", parammap)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return nil
	}
	if (len(result) == 1) {//拼装返回结构体
		resultMap := result[0]
		return resultMap//返回Map
	} else {
		logger.Error("数据库操作异常,QUERYONEMAP查出["+strconv.Itoa(len(result))+"]条记录")
		return nil
	}
}
func QUERYLISTMAP_TEMPLATE(mappermodule MapperModule, parammap map[string]interface{}) ([]map[string]interface{}) {
	result, err := QUERY_TEMPLATE(mappermodule, "querylistmap", parammap)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return nil
	}
	return result//返回Map
}
func QUERYFORPAGE_TEMPLATE(mappermodule MapperModule, parammap map[string]interface{}) ([]map[string]interface{}) {
	result, err := QUERY_TEMPLATE(mappermodule, "queryforpage", parammap)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return nil
	}
	return result//返回Map
}
func UPDATECAS_TEMPLATE(mappermodule MapperModule, parammap map[string]interface{}) (int) {
	result, err := EXEC_TEMPLATE(mappermodule, "updatecas", parammap)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return 0
	}
	return result
}
func INSERTBATCH_TEMPLATE(mappermodule MapperModule, parammaps []map[string]interface{}) (int) {
	result, err := EXEC_TEMPLATE(mappermodule, "insertbatch", parammaps)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return 0
	}
	return result
}
func UPDATEBATCH_TEMPLATE(mappermodule MapperModule, parammaps []map[string]interface{}) (int) {
	result, err := EXEC_TEMPLATE(mappermodule, "updatebatch", parammaps)
	if (err != nil) {
		logger.Error("数据库操作异常[" + err.Error() + "]")
		return 0
	}
	return result
}